home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / ghostview / Draw.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  17KB  |  913 lines

  1. /*
  2.  * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and its
  5.  * documentation for any purpose and without fee is hereby granted, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Software Research Associates not be used
  9.  * in advertising or publicity pertaining to distribution of the software
  10.  * without specific, written prior permission.  Software Research Associates
  11.  * makes no representations about the suitability of this software for any
  12.  * purpose.  It is provided "as is" without express or implied warranty.
  13.  *
  14.  * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  15.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  16.  * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
  17.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  18.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  19.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  *
  22.  * Author: Erik M. van der Poel
  23.  *         Software Research Associates, Inc., Tokyo, Japan
  24.  *         erik@sra.co.jp
  25.  */
  26.  
  27. #include <stdio.h>
  28. #include "SFinternal.h"
  29. #include "xstat.h"
  30. #include <X11/StringDefs.h>
  31. #include <X11/Xaw/Scrollbar.h>
  32.  
  33. #define SF_DEFAULT_FONT "9x15"
  34.  
  35. #define ABS(x) (((x) < 0) ? (-(x)) : (x))
  36.  
  37. typedef struct {
  38.     char *fontname;
  39. } TextData, *textPtr;
  40.  
  41. int SFcharWidth, SFcharAscent, SFcharHeight;
  42.  
  43. int SFcurrentInvert[3] = { -1, -1, -1 };
  44.  
  45. static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
  46.  
  47. static XtResource textResources[] = {
  48.     {XtNfont, XtCFont, XtRString, sizeof (char *),
  49.         XtOffset(textPtr, fontname), XtRString, SF_DEFAULT_FONT},
  50. };
  51.  
  52. static XFontStruct *SFfont;
  53.  
  54. static int SFcurrentListY;
  55.  
  56. static XtIntervalId SFscrollTimerId;
  57.  
  58. SFinitFont()
  59. {
  60.     TextData    *data;
  61.  
  62.     data = XtNew(TextData);
  63.  
  64.     XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
  65.         XtNumber(textResources), (Arg *) NULL, 0);
  66.  
  67.     SFfont = XLoadQueryFont(SFdisplay, data->fontname);
  68.     if (!SFfont) {
  69.         SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
  70.         if (!SFfont) {
  71.             char    sbuf[256];
  72.  
  73.             (void) sprintf(sbuf, "XsraSelFile: can't get font %s",
  74.                 SF_DEFAULT_FONT);
  75.  
  76.             XtAppError(SFapp, sbuf);
  77.         }
  78.     }
  79.  
  80.     SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
  81.     SFcharAscent = SFfont->max_bounds.ascent;
  82.     SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
  83. }
  84.  
  85. SFcreateGC()
  86. {
  87.     XGCValues    gcValues;
  88.     XRectangle    rectangles[1];
  89.  
  90.     gcValues.foreground = SFfore;
  91.  
  92.     SFlineGC = XtGetGC(
  93.         selFileLists[0],
  94.         (XtGCMask)
  95.             GCForeground        |
  96.             0,
  97.         &gcValues
  98.     );
  99.  
  100.     SFscrollGC = XtGetGC(
  101.         selFileLists[0],
  102.         (XtGCMask)
  103.             0,
  104.         &gcValues
  105.     );
  106.  
  107.     gcValues.function = GXinvert;
  108.     gcValues.plane_mask = (SFfore ^ SFback);
  109.  
  110.     SFinvertGC = XtGetGC(
  111.         selFileLists[0],
  112.         (XtGCMask)
  113.             GCFunction        |
  114.             GCPlaneMask        |
  115.             0,
  116.         &gcValues
  117.     );
  118.  
  119.     gcValues.foreground = SFfore;
  120.     gcValues.background = SFback;
  121.     gcValues.font = SFfont->fid;
  122.  
  123.     SFtextGC = XCreateGC(
  124.         SFdisplay,
  125.         XtWindow(selFileLists[0]),
  126.         (unsigned long)
  127.             GCForeground        |
  128.             GCBackground        |
  129.             GCFont            |
  130.             0,
  131.         &gcValues
  132.     );
  133.  
  134.     rectangles[0].x = SFlineToTextH + SFbesideText;
  135.     rectangles[0].y = 0;
  136.     rectangles[0].width = SFcharsPerEntry * SFcharWidth;
  137.     rectangles[0].height = SFupperY + 1;
  138.  
  139.     XSetClipRectangles(
  140.         SFdisplay,
  141.         SFtextGC,
  142.         0,
  143.         0,
  144.         rectangles,
  145.         1,
  146.         Unsorted
  147.     );
  148. }
  149.  
  150. SFclearList(n, doScroll)
  151.     int    n;
  152.     int    doScroll;
  153. {
  154.     SFDir    *dir;
  155.  
  156.     SFcurrentInvert[n] = -1;
  157.  
  158.     XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
  159.  
  160.     XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs,
  161.         2);
  162.  
  163.     if (doScroll) {
  164.         dir = &(SFdirs[SFdirPtr + n]);
  165.  
  166.         if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars) {
  167.             XawScrollbarSetThumb(
  168.                 selFileVScrolls[n],
  169.                 (float) (((double) dir->vOrigin) /
  170.                     dir->nEntries),
  171.                 (float) (((double) ((dir->nEntries < SFlistSize)
  172.                     ? dir->nEntries : SFlistSize)) /
  173.                     dir->nEntries)
  174.             );
  175.  
  176.             XawScrollbarSetThumb(
  177.                 selFileHScrolls[n],
  178.                 (float) (((double) dir->hOrigin) / dir->nChars),
  179.                 (float) (((double) ((dir->nChars <
  180.                     SFcharsPerEntry) ? dir->nChars :
  181.                     SFcharsPerEntry)) / dir->nChars)
  182.             );
  183.         } else {
  184.             XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
  185.                 (float) 1.0);
  186.             XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
  187.                 (float) 1.0);
  188.         }
  189.     }
  190. }
  191.  
  192. static
  193. SFdeleteEntry(dir, entry)
  194.     SFDir    *dir;
  195.     SFEntry    *entry;
  196. {
  197.     register SFEntry    *e;
  198.     register SFEntry    *end;
  199.     int            n;
  200.     int            idx;
  201.  
  202.     idx = entry - dir->entries;
  203.  
  204.     if (idx < dir->beginSelection) {
  205.         dir->beginSelection--;
  206.     }
  207.     if (idx <= dir->endSelection) {
  208.         dir->endSelection--;
  209.     }
  210.     if (dir->beginSelection > dir->endSelection) {
  211.         dir->beginSelection = dir->endSelection = -1;
  212.     }
  213.  
  214.     if (idx < dir->vOrigin) {
  215.         dir->vOrigin--;
  216.     }
  217.  
  218.     XtFree(entry->real);
  219.  
  220.     end = &(dir->entries[dir->nEntries - 1]);
  221.  
  222.     for (e = entry; e < end; e++) {
  223.         *e = *(e + 1);
  224.     }
  225.  
  226.     if (!(--dir->nEntries)) {
  227.         return;
  228.     }
  229.  
  230.     n = dir - &(SFdirs[SFdirPtr]);
  231.     if ((n < 0) || (n > 2)) {
  232.         return;
  233.     }
  234.  
  235.     XawScrollbarSetThumb(
  236.         selFileVScrolls[n],
  237.         (float) (((double) dir->vOrigin) / dir->nEntries),
  238.         (float) (((double) ((dir->nEntries < SFlistSize) ?
  239.             dir->nEntries : SFlistSize)) / dir->nEntries)
  240.     );
  241. }
  242.  
  243. static
  244. SFwriteStatChar(name, last, statBuf)
  245.     char        *name;
  246.     int        last;
  247.     struct stat    *statBuf;
  248. {
  249.     name[last] = SFstatChar(statBuf);
  250. }
  251.  
  252. static int
  253. SFstatAndCheck(dir, entry)
  254.     SFDir    *dir;
  255.     SFEntry    *entry;
  256. {
  257.     struct stat    statBuf;
  258.     char        save;
  259.     int        last;
  260.  
  261.     /*
  262.      * must be restored before returning
  263.      */
  264.     save = *(dir->path);
  265.     *(dir->path) = 0;
  266.  
  267.     if (!SFchdir(SFcurrentPath)) {
  268.         last = strlen(entry->real) - 1;
  269.         entry->real[last] = 0;
  270.         entry->statDone = 1;
  271.         if (
  272.             (!stat(entry->real, &statBuf))
  273.  
  274. #ifdef S_IFLNK
  275.  
  276.              || (!lstat(entry->real, &statBuf))
  277.  
  278. #endif /* ndef S_IFLNK */
  279.  
  280.         ) {
  281.             if (SFfunc) {
  282.                 char *shown;
  283.  
  284.                 shown = NULL;
  285.                 if (SFfunc(entry->real, &shown, &statBuf)) {
  286.                     if (shown) {
  287.                         int len;
  288.  
  289.                         len = strlen(shown);
  290.                         entry->shown = XtMalloc(
  291.                             (unsigned) (len + 2)
  292.                         );
  293.                         (void) strcpy(entry->shown,
  294.                             shown);
  295.                         SFwriteStatChar(
  296.                             entry->shown,
  297.                             len,
  298.                             &statBuf
  299.                         );
  300.                         entry->shown[len + 1] = 0;
  301.                     }
  302.                 } else {
  303.                     SFdeleteEntry(dir, entry);
  304.  
  305.                     *(dir->path) = save;
  306.                     return 1;
  307.                 }
  308.             }
  309.             SFwriteStatChar(entry->real, last, &statBuf);
  310.         } else {
  311.             entry->real[last] = ' ';
  312.         }
  313.     }
  314.  
  315.     *(dir->path) = save;
  316.     return 0;
  317. }
  318.  
  319. static
  320. SFdrawStrings(w, dir, from, to)
  321.     register Window    w;
  322.     register SFDir    *dir;
  323.     register int    from;
  324.     register int    to;
  325. {
  326.     register int        i;
  327.     register SFEntry    *entry;
  328.     int            x;
  329.  
  330.     x = SFtextX - dir->hOrigin * SFcharWidth;
  331.  
  332.     if (dir->vOrigin + to >= dir->nEntries) {
  333.         to = dir->nEntries - dir->vOrigin - 1;
  334.     }
  335.     for (i = from; i <= to; i++) {
  336.         entry = &(dir->entries[dir->vOrigin + i]);
  337.         if (!(entry->statDone)) {
  338.             if (SFstatAndCheck(dir, entry)) {
  339.                 if (dir->vOrigin + to >= dir->nEntries) {
  340.                     to = dir->nEntries - dir->vOrigin - 1;
  341.                 }
  342.                 i--;
  343.                 continue;
  344.             }
  345.         }
  346.         XDrawImageString(
  347.             SFdisplay,
  348.             w,
  349.             SFtextGC,
  350.             x,
  351.             SFtextYoffset + i * SFentryHeight,
  352.             entry->shown,
  353.             strlen(entry->shown)
  354.         );
  355.         if (dir->vOrigin + i == dir->beginSelection) {
  356.             XDrawLine(
  357.                 SFdisplay,
  358.                 w,
  359.                 SFlineGC,
  360.                 SFlineToTextH + 1,
  361.                 SFlowerY + i * SFentryHeight,
  362.                 SFlineToTextH + SFentryWidth - 2,
  363.                 SFlowerY + i * SFentryHeight
  364.             );
  365.         }
  366.         if (
  367.             (dir->vOrigin + i >= dir->beginSelection) &&
  368.             (dir->vOrigin + i <= dir->endSelection)
  369.         ) {
  370.             SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
  371.                 SFlowerY + i * SFentryHeight;
  372.             SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
  373.                 SFlowerY + (i + 1) * SFentryHeight - 1;
  374.             XDrawSegments(
  375.                 SFdisplay,
  376.                 w,
  377.                 SFlineGC,
  378.                 SFcompletionSegs,
  379.                 2
  380.             );
  381.         }
  382.         if (dir->vOrigin + i == dir->endSelection) {
  383.             XDrawLine(
  384.                 SFdisplay,
  385.                 w,
  386.                 SFlineGC,
  387.                 SFlineToTextH + 1,
  388.                 SFlowerY + (i + 1) * SFentryHeight - 1,
  389.                 SFlineToTextH + SFentryWidth - 2,
  390.                 SFlowerY + (i + 1) * SFentryHeight - 1
  391.             );
  392.         }
  393.     }
  394. }
  395.  
  396. SFdrawList(n, doScroll)
  397.     int    n;
  398.     int    doScroll;
  399. {
  400.     SFDir    *dir;
  401.     Window    w;
  402.  
  403.     SFclearList(n, doScroll);
  404.  
  405.     if (SFdirPtr + n < SFdirEnd) {
  406.         dir = &(SFdirs[SFdirPtr + n]);
  407.         w = XtWindow(selFileLists[n]);
  408.         XDrawImageString(
  409.             SFdisplay,
  410.             w,
  411.             SFtextGC,
  412.             SFtextX - dir->hOrigin * SFcharWidth,
  413.             SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
  414.             dir->dir,
  415.             strlen(dir->dir)
  416.         );
  417.         SFdrawStrings(w, dir, 0, SFlistSize - 1);
  418.     }
  419. }
  420.  
  421. SFdrawLists(doScroll)
  422.     int    doScroll;
  423. {
  424.     int    i;
  425.  
  426.     for (i = 0; i < 3; i++) {
  427.         SFdrawList(i, doScroll);
  428.     }
  429. }
  430.  
  431. static
  432. SFinvertEntry(n)
  433.     register int    n;
  434. {
  435.     XFillRectangle(
  436.         SFdisplay,
  437.         XtWindow(selFileLists[n]),
  438.         SFinvertGC,
  439.         SFlineToTextH,
  440.         SFcurrentInvert[n] * SFentryHeight + SFlowerY,
  441.         SFentryWidth,
  442.         SFentryHeight
  443.     );
  444. }
  445.  
  446. static unsigned long
  447. SFscrollTimerInterval()
  448. {
  449.     static int    maxVal = 200;
  450.     static int    varyDist = 50;
  451.     static int    minDist = 50;
  452.     int        t;
  453.     int        dist;
  454.  
  455.     if (SFcurrentListY < SFlowerY) {
  456.         dist = SFlowerY - SFcurrentListY;
  457.     } else if (SFcurrentListY > SFupperY) {
  458.         dist = SFcurrentListY - SFupperY;
  459.     } else {
  460.         return (unsigned long) 1;
  461.     }
  462.  
  463.     t = maxVal - ((maxVal / varyDist) * (dist - minDist));
  464.  
  465.     if (t < 1) {
  466.         t = 1;
  467.     }
  468.  
  469.     if (t > maxVal) {
  470.         t = maxVal;
  471.     }
  472.  
  473.     return (unsigned long) t;
  474. }
  475.  
  476. static void
  477. SFscrollTimer(n)
  478.     int    n;
  479. {
  480.     SFDir    *dir;
  481.     int    save;
  482.  
  483.     dir = &(SFdirs[SFdirPtr + n]);
  484.     save = dir->vOrigin;
  485.  
  486.     if (SFcurrentListY < SFlowerY) {
  487.         if (dir->vOrigin > 0) {
  488.             SFvSliderMovedCallback(selFileVScrolls[n], n,
  489.                 dir->vOrigin - 1);
  490.         }
  491.     } else if (SFcurrentListY > SFupperY) {
  492.         if (dir->vOrigin < dir->nEntries - SFlistSize) {
  493.             SFvSliderMovedCallback(selFileVScrolls[n], n,
  494.                 dir->vOrigin + 1);
  495.         }
  496.     }
  497.  
  498.     if (dir->vOrigin != save) {
  499.         if (dir->nEntries) {
  500.             XawScrollbarSetThumb(
  501.             selFileVScrolls[n],
  502.             (float) (((double) dir->vOrigin) / dir->nEntries),
  503.             (float) (((double) ((dir->nEntries < SFlistSize) ?
  504.                 dir->nEntries : SFlistSize)) / dir->nEntries)
  505.             );
  506.         }
  507.     }
  508.  
  509.     if (SFbuttonPressed) {
  510.         SFscrollTimerId = XtAppAddTimeOut(SFapp,
  511.             SFscrollTimerInterval(), SFscrollTimer, (XtPointer) n);
  512.     }
  513. }
  514.  
  515. static int
  516. SFnewInvertEntry(n, event)
  517.     register int        n;
  518.     register XMotionEvent    *event;
  519. {
  520.     register int    x, y;
  521.     register int    new;
  522.     static int    SFscrollTimerAdded = 0;
  523.  
  524.     x = event->x;
  525.     y = event->y;
  526.  
  527.     if (SFdirPtr + n >= SFdirEnd) {
  528.         return -1;
  529.     } else if (
  530.         (x >= 0)    && (x <= SFupperX) &&
  531.         (y >= SFlowerY)    && (y <= SFupperY)
  532.     ) {
  533.         register SFDir *dir = &(SFdirs[SFdirPtr + n]);
  534.  
  535.         if (SFscrollTimerAdded) {
  536.             SFscrollTimerAdded = 0;
  537.             XtRemoveTimeOut(SFscrollTimerId);
  538.         }
  539.  
  540.         new = (y - SFlowerY) / SFentryHeight;
  541.         if (dir->vOrigin + new >= dir->nEntries) {
  542.             return -1;
  543.         }
  544.         return new;
  545.     } else {
  546.         if (SFbuttonPressed) {
  547.             SFcurrentListY = y;
  548.             if (!SFscrollTimerAdded) {
  549.                 SFscrollTimerAdded = 1;
  550.                 SFscrollTimerId = XtAppAddTimeOut(SFapp,
  551.                     SFscrollTimerInterval(), SFscrollTimer,
  552.                     (XtPointer) n);
  553.             }
  554.         }
  555.  
  556.         return -1;
  557.     }
  558. }
  559.  
  560. /* ARGSUSED */
  561. void
  562. SFenterList(w, n, event)
  563.     Widget                w;
  564.     register int            n;
  565.     register XEnterWindowEvent    *event;
  566. {
  567.     register int    new;
  568.  
  569.     /* sanity */
  570.     if (SFcurrentInvert[n] != -1) {
  571.         SFinvertEntry(n);
  572.         SFcurrentInvert[n] = -1;
  573.     }
  574.  
  575.     new = SFnewInvertEntry(n, (XMotionEvent *) event);
  576.     if (new != -1) {
  577.         SFcurrentInvert[n] = new;
  578.         SFinvertEntry(n);
  579.     }
  580. }
  581.  
  582. /* ARGSUSED */
  583. void
  584. SFleaveList(w, n, event)
  585.     Widget        w;
  586.     register int    n;
  587.     XEvent        *event;
  588. {
  589.     if (SFcurrentInvert[n] != -1) {
  590.         SFinvertEntry(n);
  591.         SFcurrentInvert[n] = -1;
  592.     }
  593. }
  594.  
  595. /* ARGSUSED */
  596. void
  597. SFmotionList(w, n, event)
  598.     Widget            w;
  599.     register int        n;
  600.     register XMotionEvent    *event;
  601. {
  602.     register int    new;
  603.  
  604.     new = SFnewInvertEntry(n, event);
  605.  
  606.     if (new != SFcurrentInvert[n]) {
  607.         if (SFcurrentInvert[n] != -1) {
  608.             SFinvertEntry(n);
  609.         }
  610.         SFcurrentInvert[n] = new;
  611.         if (new != -1) {
  612.             SFinvertEntry(n);
  613.         }
  614.     }
  615. }
  616.  
  617. /* ARGSUSED */
  618. void
  619. SFvFloatSliderMovedCallback(w, n, fnew)
  620.     Widget    w;
  621.     int    n;
  622.     float    *fnew;
  623. {
  624.     int    new;
  625.  
  626.     new = (*fnew) * SFdirs[SFdirPtr + n].nEntries;
  627.  
  628.     SFvSliderMovedCallback(w, n, new);
  629. }
  630.  
  631. /* ARGSUSED */
  632. void
  633. SFvSliderMovedCallback(w, n, new)
  634.     Widget    w;
  635.     int    n;
  636.     int    new;
  637. {
  638.     int        old;
  639.     register Window    win;
  640.     SFDir        *dir;
  641.  
  642.     dir = &(SFdirs[SFdirPtr + n]);
  643.  
  644.     old = dir->vOrigin;
  645.     dir->vOrigin = new;
  646.  
  647.     if (old == new) {
  648.         return;
  649.     }
  650.  
  651.     win = XtWindow(selFileLists[n]);
  652.  
  653.     if (ABS(new - old) < SFlistSize) {
  654.         if (new > old) {
  655.             XCopyArea(
  656.                 SFdisplay,
  657.                 win,
  658.                 win,
  659.                 SFscrollGC,
  660.                 SFlineToTextH,
  661.                 SFlowerY + (new - old) * SFentryHeight,
  662.                 SFentryWidth + SFlineToTextH,
  663.                 (SFlistSize - (new - old)) * SFentryHeight,
  664.                 SFlineToTextH,
  665.                 SFlowerY
  666.             );
  667.             XClearArea(
  668.                 SFdisplay,
  669.                 win,
  670.                 SFlineToTextH,
  671.                 SFlowerY + (SFlistSize - (new - old)) *
  672.                     SFentryHeight,
  673.                 SFentryWidth + SFlineToTextH,
  674.                 (new - old) * SFentryHeight,
  675.                 False
  676.             );
  677.             SFdrawStrings(win, dir, SFlistSize - (new - old),
  678.                 SFlistSize - 1);
  679.         } else {
  680.             XCopyArea(
  681.                 SFdisplay,
  682.                 win,
  683.                 win,
  684.                 SFscrollGC,
  685.                 SFlineToTextH,
  686.                 SFlowerY,
  687.                 SFentryWidth + SFlineToTextH,
  688.                 (SFlistSize - (old - new)) * SFentryHeight,
  689.                 SFlineToTextH,
  690.                 SFlowerY + (old - new) * SFentryHeight
  691.             );
  692.             XClearArea(
  693.                 SFdisplay,
  694.                 win,
  695.                 SFlineToTextH,
  696.                 SFlowerY,
  697.                 SFentryWidth + SFlineToTextH,
  698.                 (old - new) * SFentryHeight,
  699.                 False
  700.             );
  701.             SFdrawStrings(win, dir, 0, old - new);
  702.         }
  703.     } else {
  704.         XClearArea(
  705.             SFdisplay,
  706.             win,
  707.             SFlineToTextH,
  708.             SFlowerY,
  709.             SFentryWidth + SFlineToTextH,
  710.             SFlistSize * SFentryHeight,
  711.             False
  712.         );
  713.         SFdrawStrings(win, dir, 0, SFlistSize - 1);
  714.     }
  715. }
  716.  
  717. /* ARGSUSED */
  718. void
  719. SFvAreaSelectedCallback(w, n, pnew)
  720.     Widget    w;
  721.     int    n;
  722.     int    pnew;
  723. {
  724.     SFDir    *dir;
  725.     int    new;
  726.  
  727.     dir = &(SFdirs[SFdirPtr + n]);
  728.  
  729.     new = dir->vOrigin +
  730.         (((double) pnew) / SFvScrollHeight) * dir->nEntries;
  731.  
  732.     if (new > dir->nEntries - SFlistSize) {
  733.         new = dir->nEntries - SFlistSize;
  734.     }
  735.  
  736.     if (new < 0) {
  737.         new = 0;
  738.     }
  739.  
  740.     if (dir->nEntries) {
  741.         float    f;
  742.  
  743.         f = ((double) new) / dir->nEntries;
  744.  
  745.         XawScrollbarSetThumb(
  746.             w,
  747.             f,
  748.             (float) (((double) ((dir->nEntries < SFlistSize) ?
  749.                 dir->nEntries : SFlistSize)) / dir->nEntries)
  750.         );
  751.     }
  752.  
  753.     SFvSliderMovedCallback(w, n, new);
  754. }
  755.  
  756. /* ARGSUSED */
  757. void
  758. SFhSliderMovedCallback(w, n, new)
  759.     Widget    w;
  760.     int    n;
  761.     float    *new;
  762. {
  763.     SFDir    *dir;
  764.     int    save;
  765.  
  766.     dir = &(SFdirs[SFdirPtr + n]);
  767.     save = dir->hOrigin;
  768.     dir->hOrigin = (*new) * dir->nChars;
  769.     if (dir->hOrigin == save) {
  770.         return;
  771.     }
  772.  
  773.     SFdrawList(n, SF_DO_NOT_SCROLL);
  774. }
  775.  
  776. /* ARGSUSED */
  777. void
  778. SFhAreaSelectedCallback(w, n, pnew)
  779.     Widget    w;
  780.     int    n;
  781.     int    pnew;
  782. {
  783.     SFDir    *dir;
  784.     int    new;
  785.  
  786.     dir = &(SFdirs[SFdirPtr + n]);
  787.  
  788.     new = dir->hOrigin +
  789.         (((double) pnew) / SFhScrollWidth) * dir->nChars;
  790.  
  791.     if (new > dir->nChars - SFcharsPerEntry) {
  792.         new = dir->nChars - SFcharsPerEntry;
  793.     }
  794.  
  795.     if (new < 0) {
  796.         new = 0;
  797.     }
  798.  
  799.     if (dir->nChars) {
  800.         float    f;
  801.  
  802.         f = ((double) new) / dir->nChars;
  803.  
  804.         XawScrollbarSetThumb(
  805.             w,
  806.             f,
  807.             (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
  808.                 dir->nChars : SFcharsPerEntry)) / dir->nChars)
  809.         );
  810.  
  811.         SFhSliderMovedCallback(w, n, &f);
  812.     }
  813. }
  814.  
  815. /* ARGSUSED */
  816. void
  817. SFpathSliderMovedCallback(w, client_data, new)
  818.     Widget        w;
  819.     XtPointer    client_data;
  820.     float    *new;
  821. {
  822.     SFDir        *dir;
  823.     int        n;
  824.     XawTextPosition    pos;
  825.     int    SFdirPtrSave;
  826.  
  827.     SFdirPtrSave = SFdirPtr;
  828.     SFdirPtr = (*new) * SFdirEnd;
  829.     if (SFdirPtr == SFdirPtrSave) {
  830.         return;
  831.     }
  832.  
  833.     SFdrawLists(SF_DO_SCROLL);
  834.  
  835.     n = 2;
  836.     while (SFdirPtr + n >= SFdirEnd) {
  837.         n--;
  838.     }
  839.  
  840.     dir = &(SFdirs[SFdirPtr + n]);
  841.  
  842.     pos = dir->path - SFcurrentPath;
  843.  
  844.     if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
  845.         pos -= strlen(SFstartDir);
  846.         if (pos < 0) {
  847.             pos = 0;
  848.         }
  849.     }
  850.  
  851.     XawTextSetInsertionPoint(selFileField, pos);
  852. }
  853.  
  854. /* ARGSUSED */
  855.  
  856. void
  857. SFpathAreaSelectedCallback(w, client_data, pnew)
  858.     Widget        w;
  859.     XtPointer    client_data;
  860.     int        pnew;
  861. {
  862.     int    new;
  863.     float    f;
  864.  
  865.     new = SFdirPtr + (((double) pnew) / SFpathScrollWidth) * SFdirEnd;
  866.  
  867.     if (new > SFdirEnd - 3) {
  868.         new = SFdirEnd - 3;
  869.     }
  870.  
  871.     if (new < 0) {
  872.         new = 0;
  873.     }
  874.  
  875.     f = ((double) new) / SFdirEnd;
  876.  
  877.     XawScrollbarSetThumb(
  878.         w,
  879.         f,
  880.         (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
  881.             SFdirEnd)
  882.     );
  883.  
  884.     SFpathSliderMovedCallback(w, (XtPointer) NULL, &f);
  885. }
  886.  
  887. Boolean
  888. SFworkProc()
  889. {
  890.     register SFDir        *dir;
  891.     register SFEntry    *entry;
  892.  
  893.     for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
  894.         if (!(dir->nEntries)) {
  895.             continue;
  896.         }
  897.         for (
  898.             entry = &(dir->entries[dir->nEntries - 1]);
  899.             entry >= dir->entries;
  900.             entry--
  901.         ) {
  902.             if (!(entry->statDone)) {
  903.                 (void) SFstatAndCheck(dir, entry);
  904.                 return False;
  905.             }
  906.         }
  907.     }
  908.  
  909.     SFworkProcAdded = 0;
  910.  
  911.     return True;
  912. }
  913.